<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">{{title}}</div>
    <script>
      // 1.基本结构
      const Vue = {
        createApp(options) {
          return {
            mount(selector) {
              // 1. 找到宿主元素
              const parent = document.querySelector(selector);
              // 2. 渲染页面
              if (!options.render) {
                //  2.1 处理template：编译
                options.render = this.compile(parent.innerHTML);
              }
              // setup和其他选项
              if (options.setup) {
                this.setupState = options.setup();
              }
              if (options.data) {
                this.data = options.data();
              }
              // app.xxx
              const proxy = new Proxy(this, {
                get(target, key) {
                  // 先从setup中取，如果娶不到再从data中取
                  if (target.setupState && key in target.setupState) {
                    return target.setupState[key];
                  } else {
                    return target.data[key];
                  }
                },
                set(target, key, val) {
                  if (target.setupState && key in target.setupState) {
                    target.setupState[key] = val;
                  } else {
                    target.data[key] = val;
                  }
                },
              });

              //  2.2 用户直接编写render
              const el = options.render.call(proxy);
              // 3. 追加到宿主
              parent.innerHTML = ""
              parent.appendChild(el);
            },
            compile(template) {
              // 返回一个render函数
              // parse -> ast
              // generate -> ast => render
              return function render() {
                const h3 = document.createElement("h3");
                h3.textContent = this.title;
                return h3;
              };
            },
          };
        },
      };
    </script>
    <script>
      const app = Vue.createApp({
        data() {
          return {
            title: "hello,vue3",
          };
        },
        setup() {
          return {
            title: "vue3, hello",
          };
        },
      });
      app.mount("#app");
    </script>
  </body>
</html>
